{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting yfinance\n",
      "  Downloading yfinance-0.1.55.tar.gz (23 kB)\n",
      "Requirement already satisfied: pandas>=0.24 in /Users/ben/anaconda3/lib/python3.6/site-packages (from yfinance) (1.1.0)\n",
      "Requirement already satisfied: numpy>=1.15 in /Users/ben/anaconda3/lib/python3.6/site-packages (from yfinance) (1.19.1)\n",
      "Requirement already satisfied: requests>=2.20 in /Users/ben/anaconda3/lib/python3.6/site-packages (from yfinance) (2.24.0)\n",
      "Collecting multitasking>=0.0.7\n",
      "  Downloading multitasking-0.0.9.tar.gz (8.1 kB)\n",
      "Collecting lxml>=4.5.1\n",
      "  Downloading lxml-4.6.0-cp36-cp36m-macosx_10_9_x86_64.whl (4.6 MB)\n",
      "\u001b[K     |████████████████████████████████| 4.6 MB 2.4 MB/s eta 0:00:01\n",
      "\u001b[?25hRequirement already satisfied: python-dateutil>=2.7.3 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pandas>=0.24->yfinance) (2.8.1)\n",
      "Requirement already satisfied: pytz>=2017.2 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pandas>=0.24->yfinance) (2018.7)\n",
      "Requirement already satisfied: chardet<4,>=3.0.2 in /Users/ben/anaconda3/lib/python3.6/site-packages (from requests>=2.20->yfinance) (3.0.4)\n",
      "Requirement already satisfied: idna<3,>=2.5 in /Users/ben/anaconda3/lib/python3.6/site-packages (from requests>=2.20->yfinance) (2.10)\n",
      "Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from requests>=2.20->yfinance) (1.25.10)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /Users/ben/anaconda3/lib/python3.6/site-packages (from requests>=2.20->yfinance) (2020.6.20)\n",
      "Requirement already satisfied: six>=1.5 in /Users/ben/anaconda3/lib/python3.6/site-packages (from python-dateutil>=2.7.3->pandas>=0.24->yfinance) (1.15.0)\n",
      "Building wheels for collected packages: yfinance, multitasking\n",
      "  Building wheel for yfinance (setup.py) ... \u001b[?25ldone\n",
      "\u001b[?25h  Created wheel for yfinance: filename=yfinance-0.1.55-py2.py3-none-any.whl size=22618 sha256=e7cb7670928e6f8a5f0c3764f36859331695f7d4266ec3b1fa34e1716bc1acfd\n",
      "  Stored in directory: /Users/ben/Library/Caches/pip/wheels/68/72/87/a384b8b8139f2489024464d6f5937e6acb2054c57d25519fb9\n",
      "  Building wheel for multitasking (setup.py) ... \u001b[?25ldone\n",
      "\u001b[?25h  Created wheel for multitasking: filename=multitasking-0.0.9-py3-none-any.whl size=8367 sha256=c3ed619b5b269bd6d0ecb7c3e57a4efd06c64b6b194cea6396cec0bbcff3f48a\n",
      "  Stored in directory: /Users/ben/Library/Caches/pip/wheels/5e/8a/c4/59c699498647c7c94b14c87a904ca7540646107b3d94b7c320\n",
      "Successfully built yfinance multitasking\n",
      "Installing collected packages: multitasking, lxml, yfinance\n",
      "  Attempting uninstall: lxml\n",
      "    Found existing installation: lxml 4.2.5\n",
      "    Uninstalling lxml-4.2.5:\n",
      "      Successfully uninstalled lxml-4.2.5\n",
      "Successfully installed lxml-4.6.0 multitasking-0.0.9 yfinance-0.1.55\n"
     ]
    }
   ],
   "source": [
    "!pip install yfinance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import yfinance as yf\n",
    "\n",
    "msft = yf.Ticker(\"MSFT\")\n",
    "\n",
    "# get stock info\n",
    "msft.info\n",
    "\n",
    "# get historical market data\n",
    "hist = msft.history(period=\"max\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting pymc3\n",
      "  Downloading pymc3-3.9.3-py3-none-any.whl (1.9 MB)\n",
      "\u001b[K     |████████████████████████████████| 1.9 MB 2.1 MB/s eta 0:00:01\n",
      "\u001b[?25hRequirement already satisfied, skipping upgrade: scipy>=0.18.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3) (1.5.2)\n",
      "Collecting contextvars; python_version < \"3.7\"\n",
      "  Downloading contextvars-2.4.tar.gz (9.6 kB)\n",
      "Requirement already satisfied, skipping upgrade: dataclasses; python_version < \"3.7\" in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3) (0.7)\n",
      "Requirement already satisfied, skipping upgrade: typing-extensions>=3.7.4 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3) (3.7.4.3)\n",
      "Requirement already satisfied, skipping upgrade: h5py>=2.7.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3) (2.10.0)\n",
      "Requirement already satisfied, skipping upgrade: numpy>=1.13.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3) (1.19.1)\n",
      "Collecting fastprogress>=0.2.0\n",
      "  Downloading fastprogress-1.0.0-py3-none-any.whl (12 kB)\n",
      "Requirement already satisfied, skipping upgrade: patsy>=0.5.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3) (0.5.1)\n",
      "Requirement already satisfied, skipping upgrade: pandas>=0.18.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3) (1.1.0)\n",
      "Collecting arviz>=0.9.0\n",
      "  Downloading arviz-0.10.0-py3-none-any.whl (1.5 MB)\n",
      "\u001b[K     |████████████████████████████████| 1.5 MB 38.6 MB/s eta 0:00:01\n",
      "\u001b[?25hCollecting theano>=1.0.5\n",
      "  Downloading Theano-1.0.5.tar.gz (2.8 MB)\n",
      "\u001b[K     |████████████████████████████████| 2.8 MB 9.7 MB/s eta 0:00:01     |██████████████████████████▌     | 2.4 MB 9.7 MB/s eta 0:00:01\n",
      "\u001b[?25hCollecting immutables>=0.9\n",
      "  Downloading immutables-0.14-cp36-cp36m-macosx_10_14_x86_64.whl (52 kB)\n",
      "\u001b[K     |████████████████████████████████| 52 kB 1.4 MB/s eta 0:00:01\n",
      "\u001b[?25hRequirement already satisfied, skipping upgrade: six in /Users/ben/anaconda3/lib/python3.6/site-packages (from h5py>=2.7.0->pymc3) (1.15.0)\n",
      "Requirement already satisfied, skipping upgrade: pytz>=2017.2 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pandas>=0.18.0->pymc3) (2018.7)\n",
      "Requirement already satisfied, skipping upgrade: python-dateutil>=2.7.3 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pandas>=0.18.0->pymc3) (2.8.1)\n",
      "Requirement already satisfied, skipping upgrade: matplotlib>=3.0 in /Users/ben/.local/lib/python3.6/site-packages (from arviz>=0.9.0->pymc3) (3.2.2)\n",
      "Requirement already satisfied, skipping upgrade: netcdf4 in /Users/ben/anaconda3/lib/python3.6/site-packages (from arviz>=0.9.0->pymc3) (1.5.3)\n",
      "Requirement already satisfied, skipping upgrade: setuptools>=38.4 in /Users/ben/anaconda3/lib/python3.6/site-packages (from arviz>=0.9.0->pymc3) (49.6.0.post20200814)\n",
      "Requirement already satisfied, skipping upgrade: packaging in /Users/ben/anaconda3/lib/python3.6/site-packages (from arviz>=0.9.0->pymc3) (20.4)\n",
      "Collecting xarray>=0.16.1\n",
      "  Downloading xarray-0.16.1-py3-none-any.whl (720 kB)\n",
      "\u001b[K     |████████████████████████████████| 720 kB 6.4 MB/s eta 0:00:01\n",
      "\u001b[?25hRequirement already satisfied, skipping upgrade: cycler>=0.10 in /Users/ben/anaconda3/lib/python3.6/site-packages (from matplotlib>=3.0->arviz>=0.9.0->pymc3) (0.10.0)\n",
      "Requirement already satisfied, skipping upgrade: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from matplotlib>=3.0->arviz>=0.9.0->pymc3) (2.4.7)\n",
      "Requirement already satisfied, skipping upgrade: kiwisolver>=1.0.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from matplotlib>=3.0->arviz>=0.9.0->pymc3) (1.0.1)\n",
      "Requirement already satisfied, skipping upgrade: cftime in /Users/ben/anaconda3/lib/python3.6/site-packages (from netcdf4->arviz>=0.9.0->pymc3) (1.0.4.2)\n",
      "Building wheels for collected packages: contextvars, theano\n",
      "  Building wheel for contextvars (setup.py) ... \u001b[?25ldone\n",
      "\u001b[?25h  Created wheel for contextvars: filename=contextvars-2.4-py3-none-any.whl size=7665 sha256=5f2aa42525589b38513544967bb4af4c07203e01ccca9f6e7c45de7ae9040d74\n",
      "  Stored in directory: /Users/ben/Library/Caches/pip/wheels/41/11/53/911724983aa48deb94792432e14e518447212dd6c5477d49d3\n",
      "  Building wheel for theano (setup.py) ... \u001b[?25ldone\n",
      "\u001b[?25h  Created wheel for theano: filename=Theano-1.0.5-py3-none-any.whl size=2668095 sha256=ae96e21415933c8228c88bced1d95da4321d1145f199c69b70da53171dce1429\n",
      "  Stored in directory: /Users/ben/Library/Caches/pip/wheels/7f/80/57/2970ddd2e4961d84fb0d58196f4965deead046d29e08693e73\n",
      "Successfully built contextvars theano\n",
      "Installing collected packages: immutables, contextvars, fastprogress, xarray, arviz, theano, pymc3\n",
      "  Attempting uninstall: xarray\n",
      "    Found existing installation: xarray 0.14.1\n",
      "    Uninstalling xarray-0.14.1:\n",
      "      Successfully uninstalled xarray-0.14.1\n",
      "  Attempting uninstall: arviz\n",
      "    Found existing installation: arviz 0.6.1\n",
      "    Uninstalling arviz-0.6.1:\n",
      "      Successfully uninstalled arviz-0.6.1\n",
      "  Attempting uninstall: theano\n",
      "    Found existing installation: Theano 1.0.4\n",
      "    Uninstalling Theano-1.0.4:\n",
      "      Successfully uninstalled Theano-1.0.4\n",
      "  Attempting uninstall: pymc3\n",
      "    Found existing installation: pymc3 3.8\n",
      "    Uninstalling pymc3-3.8:\n",
      "      Successfully uninstalled pymc3-3.8\n",
      "Successfully installed arviz-0.10.0 contextvars-2.4 fastprogress-1.0.0 immutables-0.14 pymc3-3.9.3 theano-1.0.5 xarray-0.16.1\n"
     ]
    }
   ],
   "source": [
    "# later we'll use this one:\n",
    "!pip install -U pymc3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: pymc-learn in /Users/ben/anaconda3/lib/python3.6/site-packages (0.0.1rc3)\n",
      "Requirement already satisfied: pandas>=0.21.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc-learn) (1.1.0)\n",
      "Requirement already satisfied: seaborn>=0.8.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc-learn) (0.9.0)\n",
      "Requirement already satisfied: scipy>=1.0.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc-learn) (1.5.2)\n",
      "Requirement already satisfied: theano>=1.0.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc-learn) (1.0.5)\n",
      "Requirement already satisfied: numpy>=1.13.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc-learn) (1.19.1)\n",
      "Requirement already satisfied: scikit-learn>=0.19.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc-learn) (0.23.2)\n",
      "Requirement already satisfied: matplotlib>=2.1.1 in /Users/ben/.local/lib/python3.6/site-packages (from pymc-learn) (3.2.2)\n",
      "Requirement already satisfied: joblib>=0.11 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc-learn) (0.16.0)\n",
      "Requirement already satisfied: tqdm>=4.8.4 in /Users/ben/.local/lib/python3.6/site-packages (from pymc-learn) (4.47.0)\n",
      "Requirement already satisfied: pymc3>=3.4.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc-learn) (3.9.3)\n",
      "Requirement already satisfied: six>=1.10.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc-learn) (1.15.0)\n",
      "Requirement already satisfied: numpydoc>=0.7.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc-learn) (0.8.0)\n",
      "Requirement already satisfied: future>=0.16.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc-learn) (0.18.2)\n",
      "Requirement already satisfied: python-dateutil>=2.7.3 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pandas>=0.21.1->pymc-learn) (2.8.1)\n",
      "Requirement already satisfied: pytz>=2017.2 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pandas>=0.21.1->pymc-learn) (2018.7)\n",
      "Requirement already satisfied: threadpoolctl>=2.0.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from scikit-learn>=0.19.1->pymc-learn) (2.1.0)\n",
      "Requirement already satisfied: kiwisolver>=1.0.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from matplotlib>=2.1.1->pymc-learn) (1.0.1)\n",
      "Requirement already satisfied: cycler>=0.10 in /Users/ben/anaconda3/lib/python3.6/site-packages (from matplotlib>=2.1.1->pymc-learn) (0.10.0)\n",
      "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from matplotlib>=2.1.1->pymc-learn) (2.4.7)\n",
      "Requirement already satisfied: patsy>=0.5.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3>=3.4.1->pymc-learn) (0.5.1)\n",
      "Requirement already satisfied: h5py>=2.7.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3>=3.4.1->pymc-learn) (2.10.0)\n",
      "Requirement already satisfied: dataclasses; python_version < \"3.7\" in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3>=3.4.1->pymc-learn) (0.7)\n",
      "Requirement already satisfied: contextvars; python_version < \"3.7\" in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3>=3.4.1->pymc-learn) (2.4)\n",
      "Requirement already satisfied: typing-extensions>=3.7.4 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3>=3.4.1->pymc-learn) (3.7.4.3)\n",
      "Requirement already satisfied: arviz>=0.9.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3>=3.4.1->pymc-learn) (0.10.0)\n",
      "Requirement already satisfied: fastprogress>=0.2.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from pymc3>=3.4.1->pymc-learn) (1.0.0)\n",
      "Requirement already satisfied: sphinx>=1.2.3 in /Users/ben/anaconda3/lib/python3.6/site-packages (from numpydoc>=0.7.0->pymc-learn) (1.8.2)\n",
      "Requirement already satisfied: Jinja2>=2.3 in /Users/ben/anaconda3/lib/python3.6/site-packages (from numpydoc>=0.7.0->pymc-learn) (2.11.2)\n",
      "Requirement already satisfied: setuptools in /Users/ben/anaconda3/lib/python3.6/site-packages (from kiwisolver>=1.0.1->matplotlib>=2.1.1->pymc-learn) (49.6.0.post20200814)\n",
      "Requirement already satisfied: immutables>=0.9 in /Users/ben/anaconda3/lib/python3.6/site-packages (from contextvars; python_version < \"3.7\"->pymc3>=3.4.1->pymc-learn) (0.14)\n",
      "Requirement already satisfied: packaging in /Users/ben/anaconda3/lib/python3.6/site-packages (from arviz>=0.9.0->pymc3>=3.4.1->pymc-learn) (20.4)\n",
      "Requirement already satisfied: xarray>=0.16.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from arviz>=0.9.0->pymc3>=3.4.1->pymc-learn) (0.16.1)\n",
      "Requirement already satisfied: netcdf4 in /Users/ben/anaconda3/lib/python3.6/site-packages (from arviz>=0.9.0->pymc3>=3.4.1->pymc-learn) (1.5.3)\n",
      "Requirement already satisfied: Pygments>=2.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (2.3.1)\n",
      "Requirement already satisfied: docutils>=0.11 in /Users/ben/anaconda3/lib/python3.6/site-packages (from sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (0.14)\n",
      "Requirement already satisfied: snowballstemmer>=1.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (1.2.1)\n",
      "Requirement already satisfied: babel!=2.0,>=1.3 in /Users/ben/anaconda3/lib/python3.6/site-packages (from sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (2.6.0)\n",
      "Requirement already satisfied: alabaster<0.8,>=0.7 in /Users/ben/anaconda3/lib/python3.6/site-packages (from sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (0.7.12)\n",
      "Requirement already satisfied: imagesize in /Users/ben/anaconda3/lib/python3.6/site-packages (from sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (1.1.0)\n",
      "Requirement already satisfied: requests>=2.0.0 in /Users/ben/anaconda3/lib/python3.6/site-packages (from sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (2.24.0)\n",
      "Requirement already satisfied: sphinxcontrib-websupport in /Users/ben/anaconda3/lib/python3.6/site-packages (from sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (1.1.0)\n",
      "Requirement already satisfied: MarkupSafe>=0.23 in /Users/ben/anaconda3/lib/python3.6/site-packages (from Jinja2>=2.3->numpydoc>=0.7.0->pymc-learn) (1.1.0)\n",
      "Requirement already satisfied: cftime in /Users/ben/anaconda3/lib/python3.6/site-packages (from netcdf4->arviz>=0.9.0->pymc3>=3.4.1->pymc-learn) (1.0.4.2)\n",
      "Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /Users/ben/anaconda3/lib/python3.6/site-packages (from requests>=2.0.0->sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (1.25.10)\n",
      "Requirement already satisfied: chardet<4,>=3.0.2 in /Users/ben/anaconda3/lib/python3.6/site-packages (from requests>=2.0.0->sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (3.0.4)\n",
      "Requirement already satisfied: idna<3,>=2.5 in /Users/ben/anaconda3/lib/python3.6/site-packages (from requests>=2.0.0->sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (2.10)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /Users/ben/anaconda3/lib/python3.6/site-packages (from requests>=2.0.0->sphinx>=1.2.3->numpydoc>=0.7.0->pymc-learn) (2020.6.20)\n"
     ]
    }
   ],
   "source": [
    "# ... and this one, based on the previous:\n",
    "!pip install pymc-learn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "#os.environ['THEANO_FLAGS'] = 'contexts=dev0->cuda0;dev1->cuda1'\n",
    "import theano\n",
    "# if you get a warning about pygpu imports, \n",
    "# you might have to install a different version of pygpu,\n",
    "# and restart the notebook. For example:\n",
    "# !pip install pygpu==0.7.6"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Tuple\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import scipy\n",
    "\n",
    "\n",
    "def generate_data(\n",
    "    data: pd.DataFrame, window_size: int, shift: int\n",
    ") -> Tuple[np.array, np.array]:\n",
    "    '''Generates data, X and y, based on stock price\n",
    "    history given a window_size and a shift.\n",
    "    \n",
    "    The price level is extracted over a window, a\n",
    "    period of days, Finally, a day, shift days later,\n",
    "    is to be compared against.    \n",
    "\n",
    "    Parameters:\n",
    "    -----------\n",
    "    data - stock prices over time\n",
    "    window_size - window size; how many days in X\n",
    "    shift - which point to extract as y? This is\n",
    "        taken with respect to the last point in X.\n",
    "    \n",
    "    Returns:\n",
    "    --------\n",
    "    X - history of stock prices with their window\n",
    "    y - the stock prices in the future to be predicted\n",
    "    \n",
    "    X - Windows are normalized to mean 0 and then \n",
    "    differenced (each value in a window to the \n",
    "    previous values) - as percentage change. The\n",
    "    differencing step is to introduce a measure of \n",
    "    stationarity. \n",
    "    \n",
    "    y - as percentage change with respect to the\n",
    "    last value in the window.    \n",
    "    \n",
    "    This is to help to answer the following question:\n",
    "    Given the level of prices, are they going to\n",
    "    rise or to fall, and how much?    \n",
    "    '''\n",
    "    y = data.shift(shift + window_size)\n",
    "    observation_window = []\n",
    "    for i in range(window_size):\n",
    "        observation_window.append(\n",
    "            data.shift(i)\n",
    "        )\n",
    "    X = pd.concat(observation_window, axis=1)\n",
    "    y = (y - X.values[:, -1]) / X.values[:, -1]\n",
    "    X = X.pct_change(axis=1).values[:, 1:]\n",
    "    inds = (~np. isnan(X).any(axis=1)) & (~np. isnan(y))\n",
    "    X, y = X[inds], y[inds]\n",
    "    return X, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "X, y = generate_data(hist.Close, shift=1, window_size=30)\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y)\n",
    "\n",
    "\n",
    "#from sklearn.preprocessing import StandardScaler\n",
    "#scaler = StandardScaler()\n",
    "#X_train = scaler.fit_transform(X_train)\n",
    "#X_test = scaler.transform(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 30 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pd.DataFrame(X_train).hist();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "from matplotlib import pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 0, 'values')"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYsAAAEWCAYAAACXGLsWAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAZsUlEQVR4nO3dfbRddX3n8fdHnjFKQOitBMbgFO0gsR25FdQuvRFHnpSwZlHFYgVLV8YWlY6ZGePgqo4d16AtteIwOhmhRUsNSFWigIqRO44zBQG1REAlYJBEBJHHAD5Ev/PH2anXeJN97s2554H7fq111t37t39nn+9vnZv7yX5OVSFJ0o48adAFSJKGn2EhSWplWEiSWhkWkqRWhoUkqZVhIUlqZVhIPZbknUn+btB1SL1kWEizlOT3k9yQZHOSu5NcleR3B12XNBd2HXQB0ihK8hZgJfAG4HPAT4BjgWXAowMsTZoTbllIM5RkH+BdwJlV9YmqerSqflpVn66q/zhN/xOT3JzkwSSTSf7VlGVvTbIpySNJvpXk6Kb9SUlWJrk9yQ+TXJpkv/6NUvplhoU0cy8A9gQ+2dYxybOAjwF/ChwAXAl8OsnuSZ4NvBH4nap6CnAMsKF565uAk4CXAAcCDwDn93YYUvcMC2nmngbcV1Vbuuj7auCKqrq6qn4K/CWwF/BC4GfAHsBhSXarqg1VdXvzvjcAZ1fVxqr6MfBO4OQk7jrWQBgW0sz9ENi/yz/cBwJ3bp2pqp8DdwGLqmo9nS2OdwL3Jlmd5MCm6zOATza7rh4EbqUTLmO9G4bUPcNCmrl/BH5MZzdRm+/R+cMPQJIABwObAKrq76vqd5s+Bbyn6XoXcFxVLZzy2rOqNvVwHFLXDAtphqrqIeDPgPOTnJRk7yS7JTkuyXu36X4pcEKSo5PsBqygEzT/L8mzk7w0yR7Aj4DHgZ837/sQ8O4kzwBIckCSZf0YnzQdw0Kahao6F3gL8HbgB3S2BN4IfGqbft8CXgt8ALgPeCXwyqr6CZ3jFec07d8Hfg14W/PW9wNrgM8neQS4FjhybkclbV98+JEkqY1bFpKkVoaFJKmVYSFJamVYSJJaPSGvBt1///1r8eLFPVnXo48+ypOf/OSerGuYOK7R4rhGy6iO68Ybb7yvqg6YbtkTMiwWL17MDTfc0JN1TU5OMjEx0ZN1DRPHNVoc12gZ1XEluXN7y9wNJUlqZVhIkloZFpKkVoaFJKmVYSFJamVYSJJaGRaSpFaGhSSplWEhSWr1hLyCW/PP4pVXALBiyRZOb6YBNpxzwqBKkp5Q3LKQJLUyLCRJrQwLSVIrw0KS1MqwkCS1MiwkSa0MC0lSK8NCktTKsJAktfIKbo2UxVOuzpbUP25ZSJJaGRaSpFaGhSSplWEhSWo1Z2GR5MIk9yb5xpS2v0jyzSQ3JflkkoVTlr0tyfok30pyzJT2Y5u29UlWzlW9kqTtm8sti78Fjt2m7Wrg8Kp6LvBt4G0ASQ4DTgGe07znfyTZJckuwPnAccBhwGuavpKkPpqzsKiqLwH3b9P2+ara0sxeCxzUTC8DVlfVj6vqO8B64PnNa31V3VFVPwFWN30lSX00yOss/hC4pJleRCc8ttrYtAHctU37kdOtLMlyYDnA2NgYk5OTPSly8+bNPVvXMBnVca1YsmWHy8f2+uU+ozjG6Yzq99XGcY2OgYRFkrOBLcDFvVpnVa0CVgGMj4/XxMRET9Y7OTlJr9Y1TEZ1XKe3XJS3YskWzl33i1/rDadOzHFF/TGq31cbxzU6+h4WSU4HXgEcXVXVNG8CDp7S7aCmjR20S5L6pK+nziY5FvhPwIlV9diURWuAU5LskeQQ4FDgK8D1wKFJDkmyO52D4Gv6WbMkaQ63LJJ8DJgA9k+yEXgHnbOf9gCuTgJwbVW9oapuTnIpcAud3VNnVtXPmvW8EfgcsAtwYVXdPFc1S5KmN2dhUVWvmab5gh30fzfw7mnarwSu7GFpkqQZ8gpuSVIrw0KS1MqwkCS1MiwkSa0MC0lSK8NCktTKsJAktTIsJEmtDAtJUivDQpLUyrCQJLUyLCRJrQwLSVIrw0KS1MqwkCS1MiwkSa0MC0lSK8NCktTKsJAktTIsJEmtDAtJUivDQpLUyrCQJLWas7BIcmGSe5N8Y0rbfkmuTnJb83Pfpj1JzkuyPslNSZ435T2nNf1vS3LaXNUrSdq+udyy+Fvg2G3aVgJrq+pQYG0zD3AccGjzWg58EDrhArwDOBJ4PvCOrQEjSeqfOQuLqvoScP82zcuAi5rpi4CTprR/pDquBRYmeTpwDHB1Vd1fVQ8AV/OrASRJmmO79vnzxqrq7mb6+8BYM70IuGtKv41N2/baf0WS5XS2ShgbG2NycrInBW/evLln6xomozquFUu27HD52F6/3GcUxzidUf2+2jiu0dHvsPhnVVVJqofrWwWsAhgfH6+JiYmerHdycpJerWuYjOq4Tl95xQ6Xr1iyhXPX/eLXesOpE3NcUX+M6vfVxnGNjn6fDXVPs3uJ5ue9Tfsm4OAp/Q5q2rbXLknqo36HxRpg6xlNpwGXT2l/XXNW1FHAQ83uqs8BL0+yb3Ng++VNmySpj+ZsN1SSjwETwP5JNtI5q+kc4NIkZwB3Aq9qul8JHA+sBx4DXg9QVfcn+XPg+qbfu6pq24Pm0nYt3s5uqw3nnNDnSqTRNmdhUVWv2c6io6fpW8CZ21nPhcCFPSxNkjRDXsEtSWplWEiSWhkWkqRWhoUkqZVhIUlqZVhIkloZFpKkVoaFJKmVYSFJamVYSJJaGRaSpFaGhSSplWEhSWplWEiSWhkWkqRWhoUkqZVhIUlqZVhIkloZFpKkVoaFJKlVa1gkuTHJmUn27UdBkqTh082WxauBA4Hrk6xOckySzHFdkqQh0hoWVbW+qs4GngX8PXAhcGeS/5Jkv9l8aJJ/n+TmJN9I8rEkeyY5JMl1SdYnuSTJ7k3fPZr59c3yxbP5TEnS7HV1zCLJc4Fzgb8A/gH4PeBh4Isz/cAki4A3A+NVdTiwC3AK8B7gfVX1G8ADwBnNW84AHmja39f0kyT1UVfHLOj8kb4eeG5Vvbmqrquqc4E7Zvm5uwJ7JdkV2Bu4G3gpcFmz/CLgpGZ6WTNPs/xod4NJUn+lqnbcIXlmVc02FLa3zrOAdwOPA58HzgKubbYeSHIwcFVVHZ7kG8CxVbWxWXY7cGRV3bfNOpcDywHGxsaOWL16dU9q3bx5MwsWLOjJuobJqI5r3aaHdrh8bC+45/H29SxZtE+PKuqPUf2+2jiu4bJ06dIbq2p8umW7dvH+P0ry3qp6EKA5K2pFVb19NsU0718GHAI8CHwcOHY265qqqlYBqwDGx8drYmJiZ1cJwOTkJL1a1zAZ1XGdvvKKHS5fsWQL565r/7XecOpEjyrqj1H9vto4rtHRzTGL47YGBUBVPQAcvxOf+TLgO1X1g6r6KfAJ4EXAwma3FMBBwKZmehNwMECzfB/ghzvx+ZKkGeomLHZJssfWmSR7AXvsoH+b7wJHJdm7OfZwNHALcA1wctPnNODyZnpNM0+z/IvVtu9MktRT3eyGuhhYm+RvmvnX84sDzjNWVdcluQz4KrAF+Bqd3UdXAKuT/Nem7YLmLRcAH02yHrifzplTkqQ+ag2LqnpPkpvobAEA/HlVfW5nPrSq3gG8Y5vmO4DnT9P3R3RO1dU8srjl2ISk/upmy4Kqugq4ao5rkSQNqW6us/i3SW5L8lCSh5M8kuThfhQnSRoO3WxZvBd4ZVXdOtfFSJKGUzdnQ91jUEjS/NbNlsUNSS4BPgX8eGtjVX1izqqSJA2VbsLiqcBjwMuntBWdi+kkSfNAN6fOvr4fhUiShlc3Z0M9K8na5oZ+JHluklndF0qSNJq6OcD9v4C3AT8FqKqb8CpqSZpXugmLvavqK9u0bZmLYiRJw6mbsLgvyb+kc1CbJCfTeViRJGme6OZsqDPp3OjvN5NsAr4DvHZOq5IkDZVuzoa6A3hZkicDT6qqR+a+LEnSMGkNiyR/ts08AFX1rjmqSZI0ZLrZDfXolOk9gVcA3v5DkuaRbnZDnTt1PslfAjv1PAtJ0mjp5myobe1N5xnZkqR5optjFutoTpsFdgEOADxeIUnzSDfHLF4xZXoLnVuWe1GeJM0j3YTFtqfKPnXrGVEAVXV/TyuSJA2dbsLiq8DBwANAgIXAd5tlBTxzbkqTJA2Lbg5wX03nsar7V9XT6OyW+nxVHVJVBoUkzQPdhMVRVXXl1pmqugp44c58aJKFSS5L8s0ktyZ5QZL9klyd5Lbm575N3yQ5L8n6JDcled7OfLYkaea6CYvvJXl7ksXN62zgezv5ue8HPltVvwn8Fp2L/FYCa6vqUGBtMw9wHHBo81oOfHAnP1uSNEPdhMVr6Jwu+0k6j1I9oGmblST7AC8GLgCoqp9U1YPAMuCipttFwEnN9DLgI9VxLbAwydNn+/mSpJnr5gru+4Gzkjy5qh5t69+FQ4AfAH+T5LeAG4GzgLGq2nrr8+8DY830IuCuKe/f2LR5m3RJ6pNU1Y47JC8EPgwsqKp/0fyB/3dV9Sez+sBkHLgWeFFVXZfk/cDDwJuqauGUfg9U1b5JPgOcU1VfbtrXAm+tqhu2We9yOrupGBsbO2L16tWzKe9XbN68mQULFvRkXcNk2Me1btNDs3rf2F5wz+Pt/ZYs2mdW6x+UYf++ZstxDZelS5feWFXj0y3r5tTZ9wHHAGsAquqfkrx4J+rZCGysquua+cvoHJ+4J8nTq+ruZjfTvc3yTXRO3d3qoKbtl1TVKjrP3WB8fLwmJiZ2osRfmJycpFfrGibDPq7TV14xq/etWLKFc9e1/1pvOHViVusflGH/vmbLcY2Oru4NVVV3bdP0s9l+YFV9H7grybObpqOBW+iE0WlN22nA5c30GuB1zVlRRwEPTdldJUnqg262LO5qdkVVkt3oHF/Y2VuUvwm4OMnuwB3A6+kE16VJzgDuBF7V9L0SOB5YDzzW9JUk9VE3YfEGOqe6LqKz++fzdB61OmtV9XVguv1iR0/Tt3b28yRJO2eHYZFkF+D9VXVqn+qRJA2hHR6zqKqfAc9odhdJkuapbnZD3QH83yRrmPKI1ar6qzmrSpI0VLa7ZZHko83kicBnmr5PmfKSJM0TO9qyOCLJgXRuR/6BPtUjSRpCOwqLD9G5od8hwNSrpYPPsZCkeWW7YVFV5wHnJflgVf1xH2uS5tziHVwhvuGcE/pYiTQaWq/gNigkSV3d7kOSNL8ZFpKkVoaFJKmVYSFJamVYSJJaGRaSpFaGhSSplWEhSWplWEiSWhkWkqRW3TzPQpozO7pHk6Th4ZaFJKmVYSFJamVYSJJaGRaSpFYDC4skuyT5WpLPNPOHJLkuyfoklyTZvWnfo5lf3yxfPKiaJWm+GuSWxVnArVPm3wO8r6p+A3gAOKNpPwN4oGl/X9NPktRHAwmLJAcBJwAfbuYDvBS4rOlyEXBSM72smadZfnTTX5LUJ6mq/n9ochnw34CnAP8BOB24ttl6IMnBwFVVdXiSbwDHVtXGZtntwJFVdd8261wOLAcYGxs7YvXq1T2pdfPmzSxYsKAn6xomwzKudZse6un6xvaCex7fuXUsWbRPb4rpoWH5vnrNcQ2XpUuX3lhV49Mt6/tFeUleAdxbVTcmmejVeqtqFbAKYHx8vCYmerPqyclJerWuYTIs4zq9xxflrViyhXPX7dyv9YZTJ3pTTA8Ny/fVa45rdAziCu4XAScmOR7YE3gq8H5gYZJdq2oLcBCwqem/CTgY2JhkV2Af4If9L1uS5q++H7OoqrdV1UFVtRg4BfhiVZ0KXAOc3HQ7Dbi8mV7TzNMs/2INYt+ZJM1jw3SdxVuBtyRZDzwNuKBpvwB4WtP+FmDlgOqTpHlroDcSrKpJYLKZvgN4/jR9fgT8Xl8LkyT9kmHaspAkDSnDQpLUyrCQJLUyLCRJrQwLSVIrw0KS1MqwkCS1MiwkSa0MC0lSK8NCktTKsJAktTIsJEmtBnojQWkYLd7OA5k2nHNCnyuRhodbFpKkVoaFJKmVYSFJamVYSJJaeYBbfbG9g8aSRoNbFpKkVoaFJKmVYSFJamVYSJJa9T0skhyc5JoktyS5OclZTft+Sa5Oclvzc9+mPUnOS7I+yU1JntfvmiVpvhvElsUWYEVVHQYcBZyZ5DBgJbC2qg4F1jbzAMcBhzav5cAH+1+yJM1vfQ+Lqrq7qr7aTD8C3AosApYBFzXdLgJOaqaXAR+pjmuBhUme3ueyJWleS1UN7sOTxcCXgMOB71bVwqY9wANVtTDJZ4BzqurLzbK1wFur6oZt1rWczpYHY2NjR6xevbonNW7evJkFCxb0ZF3DpN/jWrfpob58zthecM/jc7PuJYv2mZsVd8Hfw9EyquNaunTpjVU1Pt2ygV2Ul2QB8A/An1bVw5186KiqSjKjFKuqVcAqgPHx8ZqYmOhJnZOTk/RqXcOk3+M6vU8X5a1YsoVz183Nr/WGUyfmZL3d8PdwtDwRxzWQs6GS7EYnKC6uqk80zfds3b3U/Ly3ad8EHDzl7Qc1bZKkPhnE2VABLgBuraq/mrJoDXBaM30acPmU9tc1Z0UdBTxUVXf3rWBJ0kB2Q70I+ANgXZKvN23/GTgHuDTJGcCdwKuaZVcCxwPrgceA1/e3XElS38OiOVCd7Sw+epr+BZw5p0VJknbIK7glSa28RbnUJZ/NrfnMLQtJUivDQpLUyt1Q6imfiCc9MbllIUlqZVhIkloZFpKkVoaFJKmVYSFJamVYSJJaGRaSpFZeZyHtJG8DovnALQtJUivDQpLUyt1QmhVv6yHNL25ZSJJaGRaSpFbuhpLmiGdJ6YnELQtJUiu3LLRDHsiWBIaF1HfuntIoMiwEuAUhacdG5phFkmOTfCvJ+iQrB12PJM0nI7FlkWQX4Hzg3wAbgeuTrKmqWwZb2XDqZithxZItnO7WxFDZ0fc23fflbiv100iEBfB8YH1V3QGQZDWwDJgXYeEuIk1nGH8vDLD+6fexr1TVnKy4l5KcDBxbVX/UzP8BcGRVvXFKn+XA8mb22cC3evTx+wP39Whdw8RxjRbHNVpGdVzPqKoDplswKlsWrapqFbCq1+tNckNVjfd6vYPmuEaL4xotT8RxjcoB7k3AwVPmD2raJEl9MCphcT1waJJDkuwOnAKsGXBNkjRvjMRuqKrakuSNwOeAXYALq+rmPn18z3dtDQnHNVoc12h5wo1rJA5wS5IGa1R2Q0mSBsiwkCS1Miy2kWS/JFcnua35ue80fX47yT8muTnJTUlePYhaZ6KbcTX9PpvkwSSf6XeNM9F2+5ckeyS5pFl+XZLF/a9y5roY14uTfDXJlub6o5HQxbjekuSW5t/T2iTPGESdM9XFuN6QZF2Sryf5cpLDBlFnT1SVrykv4L3AymZ6JfCeafo8Czi0mT4QuBtYOOjad3ZczbKjgVcCnxl0zTsYyy7A7cAzgd2BfwIO26bPnwAfaqZPAS4ZdN09Gtdi4LnAR4CTB11zD8e1FNi7mf7jJ9D39dQp0ycCnx103bN9uWXxq5YBFzXTFwEnbduhqr5dVbc1098D7gWmvepxiLSOC6Cq1gKP9KuoWfrn279U1U+Arbd/mWrqeC8Djk6SPtY4G63jqqoNVXUT8PNBFDhL3Yzrmqp6rJm9ls61VMOum3E9PGX2ycDInlFkWPyqsaq6u5n+PjC2o85Jnk/nfxW3z3VhO2lG4xpyi4C7psxvbNqm7VNVW4CHgKf1pbrZ62Zco2im4zoDuGpOK+qNrsaV5Mwkt9PZun9zn2rruZG4zqLXknwB+PVpFp09daaqKsl2/yeQ5OnAR4HTqmrg/9Pr1bikQUnyWmAceMmga+mVqjofOD/J7wNvB04bcEmzMi/Doqpetr1lSe5J8vSqursJg3u30++pwBXA2VV17RyVOiO9GNeI6Ob2L1v7bEyyK7AP8MP+lDdrT9Tb2nQ1riQvo/Mfm5dU1Y/7VNvOmOn3tRr44JxWNIfcDfWr1vCL5D8NuHzbDs0tRz4JfKSqLutjbTujdVwjpJvbv0wd78nAF6s5yjjEnqi3tWkdV5J/DfxP4MSqGpX/yHQzrkOnzJ4A3NbH+npr0EfYh+1FZ7/2Wjpf6heA/Zr2ceDDzfRrgZ8CX5/y+u1B176z42rm/w/wA+BxOvtgjxl07dsZz/HAt+kcKzq7aXsXnT82AHsCHwfWA18Bnjnomns0rt9pvpdH6Wwp3Tzomns0ri8A90z597Rm0DX3aFzvB25uxnQN8JxB1zzbl7f7kCS1cjeUJKmVYSFJamVYSJJaGRaSpFaGhSSplWEhzbEkmwddg7SzDAtJUivDQpqhJOckOXPK/DuTvL15DsNXm+cXbHsXXJJMTH1OSJL/nuT0ZvqIJP87yY1JPtfckoUkb57ynIfVfRieNK15eW8oaSddAvw1cH4z/yrgGOC8qno4yf7AtUnWVBdXvSbZDfgAsKyqftA8TOvdwB/SefbIIVX14yQL52IwUjcMC2mGquprSX4tyYF0nmPyAJ3bvr8vyYvpPGtiEZ3bwH+/i1U+GzgcuLp55MYudB6oBXATcHGSTwGf6ulApBkwLKTZ+TidGxT+Op0tjVPpBMcRVfXTJBvo3J9qqi388q7frctD5x5PL5jmc04AXkzn6YVnJ1lSnedzSH3lMQtpdi6hc5fRk+kExz7AvU1QLAWme4b0ncBhzfPBF9J5hC3At4ADkrwAOrulkjwnyZOAg6vqGuCtzWcsmNNRSdvhloU0C1V1c5KnAJuq84yQi4FPJ1kH3AB8c5r33JXkUuAbwHeArzXtP0lyMnBekn3o/Lv8azp3M/27pi10jok82I/xSdvyrrOSpFbuhpIktTIsJEmtDAtJUivDQpLUyrCQJLUyLCRJrQwLSVKr/w/F2MPS8iAjQgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pd.DataFrame(y_train).hist(bins=50)\n",
    "plt.ylabel('frequency')\n",
    "plt.xlabel('values')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.4636980784719825"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(y > 0).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x7ff53c19cb00>"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "def threshold_vector(x, threshold=0.02):\n",
    "    def threshold_scalar(f):\n",
    "        if f > threshold:\n",
    "            return 1\n",
    "        elif f < -threshold:\n",
    "            return -1\n",
    "        return 0\n",
    "    return np.vectorize(threshold_scalar)(x)\n",
    "\n",
    "y_train_classes, y_test_classes = threshold_vector(y_train), threshold_vector(y_test)\n",
    "pd.Series(threshold_vector(y)).hist(bins=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sklearn\n",
    "import scipy\n",
    "\n",
    "\n",
    "def to_one_hot(a, classes=[-1, 0, 1]):\n",
    "    \"\"\"convert from integer encoding to one-hot\"\"\"\n",
    "    b = np.zeros((a.size, 3))\n",
    "    b[np.arange(a.size), (np.rint(a)+1).astype(int)] = 1\n",
    "    return b\n",
    "\n",
    "def measure_perf(model, y_test):\n",
    "    y_pred = model.predict(X_test)\n",
    "    print('AUC: {:.3f}'.format(\n",
    "        sklearn.metrics.roc_auc_score(\n",
    "            to_one_hot(y_test), to_one_hot(y_pred), multi_class='ovo'\n",
    "    )))\n",
    "    print('mse pred: {}'.format(\n",
    "        sklearn.metrics.mean_squared_error(y_test, y_pred)\n",
    "    ))\n",
    "    if hasattr(model, 'predict_proba'):\n",
    "        y_pred_proba = model.predict_proba(X_test)\n",
    "        y_pred_reg = np.average(\n",
    "            np.repeat(\n",
    "                np.array([-1, 0, 1]).reshape(1, -1),\n",
    "                X_test.shape[0],\n",
    "                axis=0\n",
    "            ),\n",
    "            axis=1,\n",
    "            weights=y_pred_proba\n",
    "        )    \n",
    "        print('mse prob: {}'.format(\n",
    "            sklearn.metrics.mean_squared_error(y_test, y_pred_reg)\n",
    "        ))\n",
    "        \n",
    "\n",
    "assert to_one_hot(y_test_classes.astype(int)).shape[1] == 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pd.Series(y_test).hist();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pd.DataFrame(to_one_hot(y_train_classes)).hist();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ComplementNB:\n",
      "AUC: 0.573\n",
      "mse pred: 0.9378739070409572\n",
      "mse prob: 0.39530602670232257\n",
      "CategoricalNB:\n",
      "AUC: 0.500\n",
      "mse pred: 0.39530602853198343\n",
      "mse prob: 0.3938523388872352\n",
      "BayesianRidge:\n",
      "AUC: 0.500\n",
      "mse pred: 0.39518368709305485\n",
      "LinearRegression:\n",
      "AUC: 0.500\n",
      "mse pred: 0.3945542718626845\n"
     ]
    }
   ],
   "source": [
    "from sklearn.ensemble import StackingClassifier, StackingRegressor\n",
    "from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier\n",
    "from sklearn.naive_bayes import ComplementNB, CategoricalNB\n",
    "from sklearn.isotonic import IsotonicRegression\n",
    "from sklearn.linear_model import BayesianRidge, LinearRegression, LogisticRegression\n",
    "from imblearn.pipeline import make_pipeline\n",
    "\n",
    "# see also the naivebayes-predictor library that implements a wider range of supported distribution than what comes with sklearn's implementation\n",
    "\n",
    "def create_classifier(final_estimator):\n",
    "    print(f'{final_estimator.__class__.__name__}:')\n",
    "    if final_estimator._estimator_type == 'regressor':\n",
    "        estimators = [\n",
    "            ('rf', RandomForestRegressor(\n",
    "                n_estimators=100,\n",
    "                n_jobs=-1\n",
    "            ))\n",
    "        ]        \n",
    "        return StackingRegressor(\n",
    "            estimators=estimators,\n",
    "            final_estimator=final_estimator,\n",
    "        ).fit(X_train, y_train_classes)\n",
    "    else:\n",
    "        estimators = [\n",
    "            ('rf', RandomForestClassifier(\n",
    "                n_estimators=100,\n",
    "                n_jobs=-1\n",
    "            ))\n",
    "        ]                \n",
    "        return StackingClassifier(\n",
    "            estimators=estimators,\n",
    "            final_estimator=final_estimator,\n",
    "            #stack_method='predict_proba'\n",
    "        ).fit(X_train, y_train_classes)\n",
    "\n",
    "measure_perf(create_classifier(ComplementNB()), y_test_classes)\n",
    "measure_perf(create_classifier(CategoricalNB()), y_test_classes)\n",
    "measure_perf(create_classifier(BayesianRidge()), y_test_classes)\n",
    "measure_perf(create_classifier(LinearRegression()), y_test_classes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AUC: 0.513\n",
      "mse pred: 0.42291762540266914\n",
      "mse prob: 0.3962276227874193\n",
      "AUC: 0.517\n",
      "mse pred: 0.43718361711919007\n",
      "mse prob: 0.3956709350716044\n"
     ]
    }
   ],
   "source": [
    "from sklearn.calibration import CalibratedClassifierCV\n",
    "\n",
    "rf = RandomForestClassifier(n_estimators=500, n_jobs=-1).fit(X_train, y_train_classes)\n",
    "platt = CalibratedClassifierCV(rf, method='sigmoid').fit(X_train, y_train_classes)\n",
    "isotonic = CalibratedClassifierCV(rf, method='isotonic').fit(X_train, y_train_classes)\n",
    "measure_perf(platt, y_test_classes)\n",
    "measure_perf(isotonic, y_test_classes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AUC: 0.518\n",
      "mse pred: 0.4445467096180396\n",
      "mse prob: 0.3941700782328578\n"
     ]
    }
   ],
   "source": [
    "measure_perf(rf, y_test_classes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AUC: 0.500\n",
      "mse pred: 0.3951464754864403\n"
     ]
    }
   ],
   "source": [
    "from sklearn.ensemble import StackingRegressor\n",
    "from sklearn.ensemble import RandomForestRegressor\n",
    "from sklearn.linear_model import BayesianRidge\n",
    "# see also the naivebayes-predictor library that implements a wider range of supported distribution than what comes with sklearn's implementation\n",
    "estimators = [\n",
    "    ('rf', RandomForestRegressor(n_estimators=500, n_jobs=-1)),\n",
    "]\n",
    "clf = StackingRegressor(\n",
    "    estimators=estimators,\n",
    "    final_estimator=BayesianRidge()\n",
    ")\n",
    "clf.fit(X_train, y_train)\n",
    "measure_perf(clf, y_test_classes)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
